package com.duolebo.uteped_sdk.msg;

import androidx.annotation.NonNull;

import com.duolebo.uteped_sdk.UTEPedEventHandler;
import com.duolebo.uteped_sdk.utils.Const;
import com.google.gson.Gson;
import com.yc.nadalsdk.bean.FutureWeatherConfig;
import com.yc.nadalsdk.bean.Notify;
import com.yc.nadalsdk.bean.Response;
import com.yc.nadalsdk.bean.TodayWeatherConfig;
import com.yc.nadalsdk.ble.open.UteBleConnection;
import com.yc.nadalsdk.ble.open.UteBleDevice;
import com.yc.nadalsdk.constants.NotifyType;
import com.yc.nadalsdk.listener.DeviceNotifyListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

public class WeatherMessage extends BaseMessage implements DeviceNotifyListener {

    private static final String PATH = "weather";

    /**
     * BaseCallback
     *
     * @param methodChannel methodChannel
     * @param eventHandler  eventHandler
     */
    public WeatherMessage(MethodChannel methodChannel, UTEPedEventHandler eventHandler) {
        super(methodChannel, eventHandler);
    }

    @Override
    public String getPath() {
        return PATH;
    }

    @Override
    public boolean methodCallConsumed(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        if (!call.hasArgument(Const.KEY_METHOD))
            return false;

        if (super.methodCallConsumed(call, result))
            return true;

        UteBleConnection uteBleConnection = uteBleClient.getUteBleConnection();
        boolean consumed = true;
        boolean success = false;
        String method = call.argument(Const.KEY_METHOD);
        assert method != null;
        switch (method) {
            case Const.M_setTodayWeather:
                if (uteBleClient.isConnected()) {
                    Response<?> todayRsp = uteBleConnection.setTodayWeather(getTodayWeatherConfig(call));
                    success = todayRsp.getErrorCode() == Const.CODE_SUCCESS;
                }
                result.success(success);
                break;

            case Const.M_setFutureWeather:
                if (uteBleClient.isConnected()) {
                    Response<?> rsp = uteBleConnection.setFutureWeather(getFutureWeatherConfig(call));
                    success = rsp.getErrorCode() == Const.CODE_SUCCESS;
                }
                result.success(success);
                break;

            default:
                consumed = false;
        }

        return consumed;
    }

    private FutureWeatherConfig getFutureWeatherConfig(MethodCall call) {
        FutureWeatherConfig fwc = new FutureWeatherConfig();
        if (call.hasArgument(Const.TYPE_MAP)) {
            Map<String, Object> map = call.argument(Const.TYPE_MAP);
            if (map.containsKey("weatherUpdateTimeStamp")) {
                fwc.setWeatherUpdateTimeStamp((Integer) map.get("weatherUpdateTimeStamp"));
            }
            if (map.containsKey("hourWeatherList")) {
                List<Map<String, Object>> hourWeatherList = (List<Map<String, Object>>) map.get("hourWeatherList");
                setHourWeatherList(fwc, hourWeatherList);
            }
            if (map.containsKey("dayWeatherList")) {
                List<Map<String, Object>> dayWeatherList = (List<Map<String, Object>>) map.get("dayWeatherList");
                setDayWeatherList(fwc, dayWeatherList);
            }
        }
        return fwc;
    }

    private void setDayWeatherList(FutureWeatherConfig fwc, List<Map<String, Object>> dayWeatherList) {
        List<FutureWeatherConfig.DayWeather> dayWeathers = new ArrayList<>(dayWeatherList.size());
        for (Map<String, Object> map : dayWeatherList) {
            FutureWeatherConfig.DayWeather dayWeather = new FutureWeatherConfig.DayWeather();
            if (map.containsKey("phenomenon")) {
                dayWeather.setPhenomenon((Integer) map.get("phenomenon"));
            }
            if (map.containsKey("timestamp")) {
                dayWeather.setTimestamp((Integer) map.get("timestamp"));
            }
            if (map.containsKey("highestTemperature")) {
                dayWeather.setHighestTemperature((Integer) map.get("highestTemperature"));
            }
            if (map.containsKey("lowestTemperature")) {
                dayWeather.setLowestTemperature((Integer) map.get("lowestTemperature"));
            }
            if (map.containsKey("sunriseTime")) {
                dayWeather.setSunriseTime((Integer) map.get("sunriseTime"));
            }
            if (map.containsKey("sunsetTime")) {
                dayWeather.setSunsetTime((Integer) map.get("sunsetTime"));
            }
            if (map.containsKey("moonRiseTime")) {
                dayWeather.setMoonRiseTime((Integer) map.get("moonRiseTime"));
            }
            if (map.containsKey("moonSetTime")) {
                dayWeather.setMoonSetTime((Integer) map.get("moonSetTime"));
            }
            if (map.containsKey("moonPhase")) {
                dayWeather.setMoonPhase((Integer) map.get("moonPhase"));
            }
            if (map.containsKey("hum")) {
                dayWeather.setHum((Integer) map.get("hum"));
            }
            if (map.containsKey("uv")) {
                dayWeather.setUv((Integer) map.get("uv"));
            }
            dayWeathers.add(dayWeather);
        }
        fwc.setDayWeatherList(dayWeathers);
    }

    private void setHourWeatherList(FutureWeatherConfig fwc, List<Map<String, Object>> hourWeatherList) {
        List<FutureWeatherConfig.HourWeather> hourWeathers = new ArrayList<>(hourWeatherList.size());
        for (Map<String, Object> map : hourWeatherList) {
            FutureWeatherConfig.HourWeather hourWeather = new FutureWeatherConfig.HourWeather();
            if (map.containsKey("phenomenon")) {
                hourWeather.setPhenomenon((Integer) map.get("phenomenon"));
            }
            if (map.containsKey("temperature")) {
                hourWeather.setTemperature((Integer) map.get("temperature"));
            }
            if (map.containsKey("timestamp")) {
                hourWeather.setTimestamp((Integer) map.get("timestamp"));
            }
            hourWeathers.add(hourWeather);
        }
        fwc.setHourWeatherList(hourWeathers);
    }

    private TodayWeatherConfig getTodayWeatherConfig(MethodCall call) {
        TodayWeatherConfig twc = new TodayWeatherConfig();
        if (call.hasArgument(Const.TYPE_MAP)) {
            Map<String, Object> map = call.argument(Const.TYPE_MAP);
            if (map.containsKey("cityName")) {
                twc.setCityName((String) map.get("cityName"));
            }
            if (map.containsKey("currentTemperature")) {
                twc.setCurrentTemperature((Integer) map.get("currentTemperature"));
            }
            if (map.containsKey("unit")) {
                twc.setUnit((Integer) map.get("unit"));
            }
            if (map.containsKey("aqi")) {
                twc.setAqi((Integer) map.get("aqi"));
            }
            if (map.containsKey("publishTime")) {
                twc.setPublishTime((Integer) map.get("publishTime"));
            }
//            if (map.containsKey("direction")) {
//                twc.set((String) map.get("direction"));
//            }
            if (map.containsKey("lowest")) {
                twc.setLowest((Integer)  map.get("lowest"));
            }
            if (map.containsKey("highest")) {
                twc.setHighest((Integer) map.get("highest"));
            }
            if (map.containsKey("hum")) {
                twc.setHum((Integer) map.get("hum"));
            }
            if (map.containsKey("uv")) {
                twc.setUv((Integer)  map.get("uv"));
            }
            if (map.containsKey("pm25")) {
                twc.setPm25((Integer) map.get("pm25"));
            }
            if (map.containsKey("publishSource")) {
                twc.setPublishSource((String) map.get("publishSource"));
            }
            if (map.containsKey("phenomenon")) {
                twc.setPhenomenon((Integer)  map.get("phenomenon"));
            }
        }
        return twc;
    }

    @Override
    public void onNotify(@NonNull UteBleDevice uteBleDevice, @NonNull Notify notify) {
        if (notify.getType() == NotifyType.WEATHER_DATA_REQUIRED) {
            d("weather onNotify: " + new Gson().toJson(notify));
            Map<String, Object> map = new HashMap<>();
            map.put(Const.KEY_PATH, getPath());
            map.put(Const.KEY_METHOD, Const.M_setFutureWeather);
            map.put(Const.KEY_VALUE, notify.getType());
            eventHandler.publishEvent(map);
        }
    }
}
